package se.webbzon.boltzmann.editor.factory.propertyframe;

import java.awt.GridLayout;
import java.util.Collection;
import java.util.SortedSet;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import se.webbzon.boltzmann.editor.component.appearance.SimpleAppearancePanel;
import se.webbzon.boltzmann.editor.component.dependencylist.DependencyComboBox;
import se.webbzon.boltzmann.editor.component.geometry.GeometryPanel;
import se.webbzon.boltzmann.editor.component.texturelist.TextureSetEntry;
import se.webbzon.boltzmann.editor.component.texturelist.TextureSetList;
import se.webbzon.boltzmann.editor.mvc.EditorModel;
import se.webbzon.boltzmann.editor.propertyframe.WorldObjectPropertyFrame;
import se.webbzon.boltzmann.editor.propertyframe.WorldStaticObjectPropertyFrame;
import se.webbzon.boltzmann.game.object.platform.Platform;
import se.webbzon.boltzmann.game.object.waypoint.PathProgramEnum;
import se.webbzon.boltzmann.game.object.waypoint.Waypoint;
import se.webbzon.boltzmann.object.geometry.GeometryAppearance;
import se.webbzon.boltzmann.object.geometry.GeometryMask;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.appearance.Appearance3DException;

public class PlatformPropertyFrameFactory implements PropertyFrameFactory {
	
	// A sorted set of all the available textures
	private SortedSet<TextureSetEntry> textures;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new GeometryPropertyFrameFactory by using a given
	 * sorted set of available textures. **/
	public PlatformPropertyFrameFactory(SortedSet<TextureSetEntry> textures) {
		this.textures = textures;
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public String getWorldObjectName() {
		return Platform.worldObjectName;
	}

	@Override public WorldObjectPropertyFrame makePropertyFrame(EditorModel model,
																WorldObject instance) {
		return new PropertyFrameImpl(textures,model,(Platform) instance);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of a property frame. **/
	private static final class PropertyFrameImpl extends WorldStaticObjectPropertyFrame {
	
		// The geometry appearance property panel
		private final GeometryPanel geometryAppearance, geometryMask;
		
		// The simple appearance property panel
		private final SimpleAppearancePanel appearancePanel;
		
		// The texture property panel
		private final TextureSetList texturePanel;
		
		// The combo boxes of this panel
		private final DependencyComboBox<Waypoint> waypointInput;
		private final JComboBox<PathProgramEnum> programInput;
		
		// The text fields of this panel
		private final JTextField timeInput, durationInput;
	
		/*============================================================
		Constructors
		============================================================*/
	
		public PropertyFrameImpl(	SortedSet<TextureSetEntry> textures,
									EditorModel model, Platform p) {
			super(model,p);
		
			// Create geometry appearance panel
			final GeometryAppearance appearance = p.getGeometryAppearance();
			geometryAppearance = new GeometryPanel(	appearance.getGeometry(),
													appearance.isOpen(),
													appearance.getDivisions(),
													appearance.isBackfaced());
			addPanel("Geometry Appearance",geometryAppearance);
			
			// Create geometry mask panel
			final GeometryMask mask = p.getGeometryMask();
			geometryMask = new GeometryPanel(	mask.getGeometry(),
												mask.isOpen(),
												mask.getDivisions());
			addPanel("Geometry Mask",geometryMask);
		
			// Create appearance panel
			appearancePanel = 
					new SimpleAppearancePanel(appearance.getAppearance());
			addPanel(appearancePanel.getName(),appearancePanel);
			
			// Create texture panel
			texturePanel = 
					new TextureSetList(	textures,
										appearance.getTextureSetName(),
										appearance.getAppearance().getTextureIndex(),
										appearance.getAppearance().getTextureSpeed());
			addPanel(texturePanel.getName(),texturePanel);
			
			// Create platform panel
			JPanel platformPanel = new JPanel();
			platformPanel.setLayout(new BoxLayout(platformPanel,BoxLayout.Y_AXIS));
			waypointInput = 
					new DependencyComboBox<Waypoint>(	model,Waypoint.class,
														p.getWaypoint(),
														"Start Waypoint: ");
			waypointInput.setBorder(BorderFactory.createTitledBorder(waypointInput.getName()));
			platformPanel.add(waypointInput);
			
			JPanel programPanel = new JPanel();
			programPanel.setBorder(BorderFactory.createTitledBorder("Platform Program:"));
			programPanel.setLayout(new GridLayout(3,2));
			programPanel.add(new JLabel("Program:"));
			programInput = new JComboBox<PathProgramEnum>(PathProgramEnum.values());
			programInput.setSelectedItem(p.getProgram());
			programPanel.add(programInput);
			programPanel.add(new JLabel("Cycle Time (# of steps):"));
			timeInput = new JTextField("" + p.pos());
			programPanel.add(timeInput);
			programPanel.add(new JLabel("Cycle Duration (# of steps):"));
			durationInput = new JTextField("" + p.getCycleDuration());
			programPanel.add(durationInput);
			platformPanel.add(programPanel);
			addPanel("Platform",platformPanel);
			
			initialize();
		}
	
		/*============================================================
		Public Methods
		============================================================*/
	
		public boolean apply(Collection<String> errorMessages) {
			if (super.apply(errorMessages)) try {
				Platform p = (Platform) getInstance();
				GeometryMask mask = new GeometryMask(	geometryMask.getGeometry(),
														geometryMask.isOpen(),
														geometryMask.getDivisions());
				GeometryAppearance appearance = 
						new GeometryAppearance(	geometryAppearance.getGeometry(),
												geometryAppearance.isOpen(),
												geometryAppearance.getDivisions(),
												geometryAppearance.isBackfaced(),
												appearancePanel.getRenderingOrder(),
												texturePanel.getTextureSetName(),
												texturePanel.getTextureIndex(),
												texturePanel.getTextureSpeed(),
												appearancePanel.getXLayer(),
												appearancePanel.getYLayer(),
												appearancePanel.getZLayer(),
												appearancePanel.getColor(),
												appearancePanel.getTransparency(),
												appearancePanel.getHRep(),
												appearancePanel.getVRep(),
												appearancePanel.getHOffset(),
												appearancePanel.getVOffset(),
												appearancePanel.getRotation());
				appearance.getAppearance().setTextureIndex(texturePanel.getTextureIndex());
				appearance.getAppearance().setTextureIndex(texturePanel.getTextureSpeed());
				p.setGeometryMask(mask);
				p.setGeometryAppearance(appearance);
				p.setWaypoint(waypointInput.getInstance());
				p.setProgram((PathProgramEnum) programInput.getSelectedItem());
				p.setCycleDuration(Integer.parseInt(durationInput.getText()));
				p.seek(Integer.parseInt(timeInput.getText()));
				return true;
			} catch (NumberFormatException | Appearance3DException e) {
				errorMessages.add(e.getMessage());
				return false;
			} else
				return false;
		}
	
	}
	
}



